package com.service.lotterySystem.service.impl;

import com.service.config.utils.*;
import com.service.lotterySystem.dao.UserInfoDao;
import com.service.lotterySystem.dto.*;
import com.service.lotterySystem.entity.UserInfo;
import com.service.lotterySystem.rabbitmq.MsgProducer;
import com.service.lotterySystem.service.AddressService;
import com.service.lotterySystem.service.UserDataService;
import com.service.lotterySystem.service.UserInfoService;
import com.service.lotterySystem.task.SendSmsOne;
import com.service.lotterySystem.vo.UserInfoVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

import static com.service.config.constant.Constant.PARAMETER_NOT_FOUND;
import static com.service.config.constant.Constant.USER_INFO_LO;

/**
 * @author ：hjl
 * @date ：Created in 2022/01/11 17:21
 * @description：
 */
@Service
@Slf4j
public class UserInfoServiceImpl implements UserInfoService {
    @Resource
    private UserInfoDao userInfoDao;
    @Resource
    private UserDataService userDataService;
    @Resource
    private AddressService addressService;
    @Resource
    private SendSmsOne sendSmsOne;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private MsgProducer msgProducer;

    @Override
    public Result queryUserById(String uid) {
        UserInfo userInfo = userInfoDao.queryById(uid);
        if (null == userInfo)
        {
            return Result.failure(PARAMETER_NOT_FOUND,"当前用户不存在");
        }
        return Result.ok().setData(userInfo);
    }

    @Override
    public Result queryUserDetail(String uid) {
        List<ReceiveAddressDto> receiveAddressDtos = addressService.queryAddressByUid(uid);
        UserInfoAndDataDto userInfoAndDataDto = userDataService.queryUserById(uid);
        if (null == userInfoAndDataDto)
        {
            return Result.failure(PARAMETER_NOT_FOUND,"当前用户不存在");
        }
        UserInfoVo userVo = ModelMapperUtil.strictMap(userInfoAndDataDto, UserInfoVo.class);
        userVo.setAddressDto(receiveAddressDtos);
        return Result.ok().setData(userVo);
    }

    @Override
    public Result update(UserInfoDto userInfoDto) {
        UserInfo userInfo = ModelMapperUtil.strictMap(userInfoDto, UserInfo.class);
        userInfoDao.update(userInfo);
        return Result.ok();
    }

    @Override
    public Result sendSms(SmsCode smsCode)  {
        String code = verifyCode(smsCode.getTel(),6);
        smsCode.setCode(code);
        try {
            msgProducer.sendMsg(smsCode,1);
            return Result.ok();
        } catch (Exception e) {
            e.printStackTrace();
            return Result.failure("123444");
        }
    }

    /**
     * 验证手机号和验证码并生成token
     * @param smsCode
     * @return
     */
    @Override
    public Result queryByPhone(SmsCode smsCode,String shareId,String uScanTime) throws Exception {
        if (redisUtil.exist(smsCode.getCode())) {
            String value = redisUtil.getValue(smsCode.getCode());
            UserInfo userInfo1 = JsonXMLUtils.json2obj(value, UserInfo.class);
            Set<String> strings = redisUtil.redisLike(userInfo1.getId());
            if (strings.size() > 0) {
                String s = strings.stream().findFirst().get();
                s = redisUtil.getValue(s);
                clearCache(strings,redisUtil);//清除登录缓存
                String token = UserTokenManager.generateToken(userInfo1.getId());
                redisUtil.setValue(token+userInfo1.getId(),JsonXMLUtils.obj2json(userInfo1));
                HashMap map = new HashMap();
                map.put("Token",token);
                return Result.ok().setData(map) ;
            }
            UserInfo userInfo = userInfoDao.queryByPhone(smsCode.getTel());
            if (userInfo != null) {
                String token = UserTokenManager.generateToken(userInfo.getId());
                redisUtil.setValue(token+userInfo.getId(),JsonXMLUtils.obj2json(userInfo));
                HashMap map = new HashMap();
                map.put("Token",token);
                return Result.ok().setData(map) ;
            }
            userInfo = new UserInfo();
            userInfo.setId(IdUtil.getStringId());
            userInfo.setNickName(CharUtil.getCharAndNumr(16));//生成昵称
            userInfo.setRegisterTime(new Date());
            userInfo.setTelphone(smsCode.getTel());
            userInfo.setIsSignAgreement(true);
            userInfo.setUStatus(true);
            userInfo.setShareId(shareId);
            if (!StringUtils.isEmpty(uScanTime)) {
                DateUtil.timeStamp2Date(uScanTime,"yyyy-MM-dd HH:mm:ss");
                userInfo.setUScanTime(new Date());
            }
            userInfoDao.insert(userInfo);//新增
            String token = UserTokenManager.generateToken(userInfo.getId());
            redisUtil.setValue(token+userInfo.getId(),JsonXMLUtils.obj2json(userInfo));
            HashMap map = new HashMap();
            map.put("Token",token);
            return Result.ok().setData(map);
        }
        Map map = new HashMap();
        map.put("code",403);
        map.put("msg","验证码已失效，请重新发送");
        return Result.ok().setData(map);
    }

    /**
     * 验证本地是否存在重复验证码，如重复，则重新生成
     * @param tel
     * @param integer
     * @return
     */
    private String verifyCode(String tel,Integer integer) {
        String randomNum = CharUtil.getRandomNum(integer);
        if (redisUtil.exist(randomNum)) {
            verifyCode(tel,integer);
        }
        redisUtil.set(randomNum,1,tel,5);
        return randomNum;
    }
    /**
     * 清除缓存
     * @param strings
     * @param redisUtil
     */
    public static void clearCache(Set<String> strings, RedisUtil redisUtil) {
        strings.stream().forEach(
                s -> {
                    String value = redisUtil.getValue(s);
                    try {
                        UserInfo userDto1 = JsonXMLUtils.json2obj(value, UserInfo.class);
                        redisUtil.leftPush(USER_INFO_LO,JsonXMLUtils.obj2json(userDto1));
                        redisUtil.delete(s);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
        );
    }
}
